package pl.edu.agh.jemo.quicktests;

import java.io.IOException;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import pl.edu.agh.jemo.evolution.algorithm.impl.ClusteredNSGA2Algorithm;
import pl.edu.agh.jemo.evolution.algorithm.impl.NSGA2Algorithm;
import pl.edu.agh.jemo.evolution.genotype.impl.DoubleGenotype;
import pl.edu.agh.jemo.evolution.objfunc.ObjectiveFunctionSet;
import pl.edu.agh.jemo.evolution.objfunc.impl.ExtremaFinderObjectiveFunction;
import pl.edu.agh.jemo.evolution.objfunc.impl.FitnessSharingObjectiveFunction;
import pl.edu.agh.jemo.evolution.objfunc.impl.MichalewiczObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.RastriginObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.SchweffelObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.Simple2DObjFunc;
import pl.edu.agh.jemo.evolution.objfunc.impl.SimpleYetMoreComplicated2DObjectiveFunc;
import pl.edu.agh.jemo.evolution.operator.common.DomainControl;
import pl.edu.agh.jemo.evolution.operator.crossover.impl.EmptyCrossover;
import pl.edu.agh.jemo.evolution.operator.crossover.impl.LinearCrossover;
import pl.edu.agh.jemo.evolution.operator.crossover.impl.Radial2DCrossover;
import pl.edu.agh.jemo.evolution.operator.mutation.impl.BalancedMutation;
import pl.edu.agh.jemo.evolution.operator.mutation.impl.EmptyMutation;
import pl.edu.agh.jemo.evolution.operator.mutation.impl.RadialMutation;
import pl.edu.agh.jemo.evolution.population.Population;
import pl.edu.agh.jemo.evolution.selections.impl.BinaryTournament;
import pl.edu.agh.jemo.evolution.selections.impl.ClassicTournament;
import pl.edu.agh.jemo.evolution.selections.impl.EmptyTournament;
import pl.edu.agh.jemo.evolution.specimen.impl.NSGA2Specimen;
import pl.edu.agh.jemo.gui.LoggerHelper;

public class QuickClusteringNSGA2Test {
	public static void main(String[] args) throws IOException {
		
		Logger logger = LoggerHelper.getInstance().getLogger();
		LoggerHelper.getInstance().addConsoleAppender();
		logger.setLevel(Level.INFO);
		NSGA2Algorithm algorithm = new ClusteredNSGA2Algorithm();
		
		//int populationSize = 3000;
		//int steps = 20;		
		
		int populationSize = 1000;
		int steps = 2;


		
		//TODO: hybryda, loadpopulation dla 3ciego kroku zwyklej nsga i odpalic clustered

		// Objective functions
		Simple2DObjFunc simple0 = new Simple2DObjFunc();
		Simple2DObjFunc simple2 = new Simple2DObjFunc();
		SimpleYetMoreComplicated2DObjectiveFunc yet1 = new SimpleYetMoreComplicated2DObjectiveFunc();
		simple2.setZero(2.);
		simple0.setZero(0.);
		
		MichalewiczObjFunc michalewicz = new MichalewiczObjFunc();
		michalewicz.setM(2.);
		MichalewiczObjFunc michalewicz2 = new MichalewiczObjFunc();
		michalewicz2.setM(2.);
		
		SchweffelObjFunc schwefel = new SchweffelObjFunc();
		
		RastriginObjFunc rastrigin = new RastriginObjFunc();
		
		FitnessSharingObjectiveFunction fitnessSharing = new FitnessSharingObjectiveFunction();
//		fitnessSharing.setNicheRadius(2.2);
//		fitnessSharing.setNicheRadius(.75);
		fitnessSharing.setNicheRadius(.7);
		
//		PopulationCentroidObjectiveFunction populationCentroid = new PopulationCentroidObjectiveFunction();
		ExtremaFinderObjectiveFunction extrema = new ExtremaFinderObjectiveFunction();
		extrema.setRadius(0.2);
		extrema.setSampleSize(600);
		extrema.setDominationRatio(.983);
		
		ObjectiveFunctionSet set = new ObjectiveFunctionSet();
//		set.add(simple0);
//		set.add(yet1);
//		set.add(simple2);
		set.add(michalewicz);
//		set.add(schwefel);
//		set.add(michalewicz2);
//		set.add(rastrigin);
//		set.add(new PopulationCentroidObjectiveFunction());
//		set.add(fitnessSharing);
		set.add(extrema);
		algorithm.setObjectiveFunctionSet(set);

		// Mutation
		
		BalancedMutation balancedMutation = new BalancedMutation();
		balancedMutation.setDomainControl(DomainControl.MOVE_TO_BORDER);
		balancedMutation.setImproveSpecimen(false);
		balancedMutation.setMutationChance(0.15);
		balancedMutation.setStrongMutationChance(0.01);
		
		RadialMutation radialMutation = new RadialMutation();
		radialMutation.setDomainControl(DomainControl.MOVE_TO_BORDER);
		radialMutation.setImproveSpecimen(false);
		radialMutation.setMutationChance(.5);
		radialMutation.setRadius(.5);
		
		EmptyMutation emptyMutation = new EmptyMutation();
		
		algorithm.setMutation(radialMutation);
//		algorithm.setMutation(emptyMutation);
//		algorithm.setMutation(balancedMutation);
		algorithm.setHillClimbingMultiplier(0.);

		// Crossover
		
		Radial2DCrossover radialCrossover = new Radial2DCrossover();
		radialCrossover.setCrossoverChance(0.5);
		radialCrossover.setDomainControl(DomainControl.MOVE_TO_BORDER);
		radialCrossover.setImproveSpecimen(false);

		LinearCrossover linearCrossover = new LinearCrossover();
		linearCrossover.setCrossoverChance(0.15);
		linearCrossover.setDomainControl(DomainControl.MOVE_TO_BORDER);
		linearCrossover.setImproveSpecimen(false);
		
		EmptyCrossover emptyCrossover = new EmptyCrossover();
		algorithm.setCrossover(radialCrossover);
//		algorithm.setCrossover(linearCrossover);
//		algorithm.setCrossover(emptyCrossover);

		// Tournament
		BinaryTournament binaryTournament = new BinaryTournament();
		EmptyTournament emptyTournament = new EmptyTournament();
		ClassicTournament classicTournament = new ClassicTournament();
		classicTournament.setProbability(.8);
		classicTournament.setTournamentSizeRatio(.8);
		classicTournament.setExpectedPopulationSize(populationSize);
		binaryTournament.setExpectedPopulationSize(populationSize);
		emptyTournament.setExpectedPopulationSize(populationSize);
		
		algorithm.setTournament(classicTournament);
//		algorithm.setTournament(binaryTournament);
//		algorithm.setTournament(emptyTournament);

		// Other
		
		Population population = new Population();
		algorithm.setPopulation(population);
		algorithm.setSteps(steps);
		algorithm.setPopulationSize(populationSize);
//		algorithm.setPopulationPath("D:\\STUDIA\\mgr\\mgr wyniki\\nsga\\pelne nsga\\nsga michalewicz fitszer.75\\Population\\1\\genotype\\p0.txt");
		algorithm.setSpecimenType(NSGA2Specimen.class);
		algorithm.setGenotypeType(DoubleGenotype.class);
	
		algorithm.start();

	}
}
